/* Copyright */
/*******************************************************************************
 * The MIT License (MIT)
 *
 * Copyright (c) 2014 Tsunagi-BPM
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *******************************************************************************/
 /* Copyright End */
 
package tsunagi.rest;

import java.io.IOException;
import java.io.InputStream;
import java.text.MessageFormat;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import tsunagi.common.SystemException;
import tsunagi.common.util.StringUtil;

@WebServlet(description = "Rest-Like Processor Servlet", urlPatterns = { "/*" })
public class RestLike extends HttpServlet {
	private static final long serialVersionUID = 1L;
	
	public void init(ServletConfig config) throws ServletException {
		ServletContext context = config.getServletContext();
		InputStream is = context.getResourceAsStream("/WEB-INF/rest-like.json");
		RestLikeUtil.getInstance(StringUtil.INSTANCE.getContent(is)); // initialize only
		
		try {
			is.close();
		} catch(Exception e) {
			throw new SystemException(e);
		}
	}

	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String url = request.getRequestURI();
		JsonData jd = null;
		if (!RestLikeUtil.getInstance().isResourceDefined(url)) {
			jd = new JsonData();
			jd.setError(Error.INSTANCE.getErrorNo(Error.ERROR_RESOURCE_NOT_DEFINED), MessageFormat.format(Error.INSTANCE.getErrorMessage(Error.ERROR_RESOURCE_NOT_DEFINED), url));
			return;
		} 
		
		String method = request.getMethod().toLowerCase();
		
		RequestAnalyzer reqAnalyzer = RestLikeUtil.getInstance().getRequestAnalyzer(method, url);
		if (reqAnalyzer == null) {
			jd = new JsonData();
			jd.setError(Error.INSTANCE.getErrorNo(Error.ERROR_REQUEST_ANALYZER_NOT_DEFINED), MessageFormat.format(Error.INSTANCE.getErrorMessage(Error.ERROR_REQUEST_ANALYZER_NOT_DEFINED), url));
			response.getWriter().write(jd.toString());
			return;
		}
		
		Object data = reqAnalyzer.execute(method, url, request.getParameterMap());
		if (data == null) {
			jd = new JsonData();
			jd.setError(Error.INSTANCE.getErrorNo(Error.ERROR_REQUEST_DATA_FAILED), MessageFormat.format(Error.INSTANCE.getErrorMessage(Error.ERROR_REQUEST_DATA_FAILED), url));
			response.getWriter().write(jd.toString());
			return;
		}
		
		IRequestProcessor reqProcessor = RestLikeUtil.getInstance().getRequestProcessor(url, method, data.getClass().getName());
		if (reqProcessor == null) {
			jd = new JsonData();
			jd.setError(Error.INSTANCE.getErrorNo(Error.ERROR_REQUEST_PROCESSOR_NOT_DEFINED), MessageFormat.format(Error.INSTANCE.getErrorMessage(Error.ERROR_REQUEST_PROCESSOR_NOT_DEFINED), url));
			response.getWriter().write(jd.toString());
			return;
		}
		
		jd = reqProcessor.execute(method, data);
		if (jd == null) {
			jd = new JsonData();
			jd.setError(Error.INSTANCE.getErrorNo(Error.ERROR_REQUEST_PROCESSING_FAILED), MessageFormat.format(Error.INSTANCE.getErrorMessage(Error.ERROR_REQUEST_PROCESSING_FAILED), url));
		}

		response.getWriter().write(jd.toString());
	}
}
